package comlib

abstract class XIterator[T] extends Iterator[T]{
  /** 向量叉积。见[[cross]] */
  def cross():cross2[T,T] = cross(this)
  /** 向量叉积。见[[cross]] */
  def cross[A](ite1:Iterator[A]):cross2[T,A] = new cross2(this,ite1)
  /** 向量叉积。见[[cross]] */
  def cross[A,B](ite1:Iterator[A], ite2:Iterator[B]):cross3[T,A,B] = new cross3(this,ite1,ite2)
  /** 向量叉积。见[[cross]] */
  def cross[A,B,C](ite1:Iterator[A], ite2:Iterator[B], ite3:Iterator[C]):cross4[T,A,B,C] = new cross4(this,ite1,ite2,ite3)
}

class iter[A](ite:Iterator[A]) extends Iterator[A]{
  def hasNext = ite.hasNext
  def next() = ite.next()
}

//================================================================================================
//  range
//================================================================================================
/**整数序列迭代器
 * @param pos 序列输入参数。格式为: (begin, [end, [step=1, [repeat=1]]])*
 * 
 * 按组顺序进行枚举求值；每组重复`repeat`次；全部枚举完成后结束迭代器
 *
 * range支持以下的模式组合
 * - begin<end && step>0 && repeat>0    => 有限递增
 * - begin<end && step>0 && repeat<=0   => 无限循环递增
 * - begin<end && step=0                => 无限begin循环
 * - begin<end && step<0                => 从begin开始，按照begin+step无限递减
 * - begin>end && step>0                => 从begin开始，按照begin+step无限递增
 * - begin>end && step=0                => 无限begin循环
 * - begin>end && step<0 && repeat>0    => 有限递减
 * - begin>end && step<0 && repeat<=0   => 无限循环递减
 * - begin==end && repeat>0             => begin循环repeat次
 * - begin==end && repeat<=0            => 无限begin循环
 */
class range(pos:Seq[Int]) extends XIterator[Int]{

  /** 当枚举到最后一组，最后一个重复，并且返回值超过step时，结束迭代 */
  def hasNext = grpPtr<posGrp.size

  def next() = {
    val ret = value   // 保持返回值
    value = value + step   // 仅更新value

    if( (begin <= end && value >= end)  /*递增满足一轮结束条件*/
      ||(begin >= end && value <= end)) /*递减满足一轮结束条件*/
      reload( rptPtr+1 >= repeat /*组更新条件*/ && repeat > 0 /*有限循环条件*/ )   // 更新新的一轮初始值

    ret
  }

  private def reload( upGrp:Boolean=true ) = {
    // if( rptPtr + 1 >= repeat /*组更新条件*/ && repeat > 0 /*有限循环条件*/ ){
    if( upGrp ){
      grpPtr = grpPtr + 1
      rptPtr = 0
    }else
      rptPtr = rptPtr + 1

    if( grpPtr < posGrp.size ){
      val grp = posGrp(grpPtr)
      begin = if( grp.size >= 1 ) grp(0) else 0
      end = if( grp.size >= 2 ) grp(1) else begin - 1
      step = if( grp.size >= 3 ) grp(2) else 1
      repeat = if( grp.size >= 4 ) grp(3) else 1
    }
    value = begin
  }

  /** 按(start, end, step, repeat)进行分组 */
  private val posGrp ={
    val ipos = if(pos.size==0) Seq(0) else pos
    ipos.grouped(4).toList
  }
  /** 当前选择的begin */
  private var begin = 0
  /** 当前选择的end */
  private var end = 0
  /** 当前选择的step */
  private var step = 0
  /** 当前选择的repeat */
  private var repeat = 0
  /** 组指针 */
  private var grpPtr = -1
  /** 重复指针 */
  private var rptPtr = 0
  /** 当前选择序号 */
  private var value = 0

  reload()
}
object range{
  def apply(pos:Int*) = new range(pos)
}


//================================================================================================
//  cross
//================================================================================================
class cross1[A](val ite:Iterator[A], val m:Int) extends XIterator[List[A]]{

  var (master, minor) = ite.duplicate
  var value1:Option[A] = if(m>1) Some(master.next()) else None
  var subCross = if(m>1){ minor.next(); new cross1[A]( minor, m-1 ) } else null

  def hasNext = master.hasNext || (subCross!=null && subCross.hasNext)

  def next():List[A] = {
    if( m == 1 ){
      List(master.next())
    }else{
      val ret = value1.get +: subCross.next()

      if( !subCross.hasNext ){
        value1 = Some(master.next())   // 继续找下一个
        val b = master.duplicate
        master = b._1 
        subCross = new cross1[A]( b._2, m-1 )
      }

      ret
    }
  }
}

class cross2[A,B](ite1:Iterator[A], ite2:Iterator[B]) extends XIterator[(A,B)]{
  
  private var (backup, iter2) = ite2.duplicate
  private var value1:Option[A] = if(ite1.hasNext) Some(ite1.next()) else None
  
  def hasNext = ite1.hasNext | iter2.hasNext

  def next() = {
    if( !iter2.hasNext ){
      val b = backup.duplicate
      backup = b._1
      iter2 = b._2
      value1 = Some(ite1.next())
    }

    (value1.get, iter2.next())
  }
}

class cross3[A,B,C](ite1:Iterator[A], ite2:Iterator[B], ite3:Iterator[C]) extends XIterator[(A,B,C)] {

  private val c2 = new cross2[(A,B),C](new cross2(ite1, ite2), ite3)

  def hasNext = c2.hasNext
  
  def next():(A,B,C) = {
    val ((a,b),c) = c2.next()
    (a,b,c)
  }
} 

class cross4[A,B,C,D](ite1:Iterator[A], ite2:Iterator[B], ite3:Iterator[C], ite4:Iterator[D]) extends XIterator[(A,B,C,D)]{

  private val c2 = new cross2[(A,B),(C,D)](new cross2(ite1, ite2), new cross2(ite3, ite4))

  def hasNext = c2.hasNext

  def next():(A,B,C,D) = {
    val ((a,b),(c,d)) = c2.next()
    (a,b,c,d)
  }
} 

/** 叉积(笛卡尔积)
 *
 * 多个向量元素的交叉组合。组合集合中的每个元素使用一个tuple表示。叉积类似于对各个向量中的元素进行排列：每个向量各出一个元素，N个向量总计N个元素构成一个tuple。然后所有tuple的
 * 集合就是向量的叉积
 */
object cross{

  def apply[A](ite:Iterator[A], m:Int=2):cross1[A] = new cross1(ite, m)

  /** 2个操作数的叉积
   * @example
   * {{{
    val ite = cross(List(1,2).iterator, List(3,4,5).iterator)
    ite.toList   // List((1,3), (1,4), (1,5), (2,3), (2,4), (2,5))
   }}}
   */
  def apply[A,B](ite1:Iterator[A], ite2:Iterator[B]):cross2[A,B] = new cross2(ite1,ite2)

  /** 3个操作数的叉积
   * @example
   * {{{
    val ite = cross(List(1,2).iterator, List(3,4).iterator, List(5,6).iterator)
    ite.toList   // List((1,3,5), (1,3,6), (1,4,5), (1,4,6), (2,3,5), (2,3,6), (2,4,5), (2,4,6))
   }}}
   */
  def apply[A,B,C](ite1:Iterator[A], ite2:Iterator[B], ite3:Iterator[C]) = new cross3(ite1,ite2,ite3)

  /** 4个操作数的叉积 */
  def apply[A,B,C,D](ite1:Iterator[A], ite2:Iterator[B], ite3:Iterator[C], ite4:Iterator[D]) = new cross4(ite1,ite2,ite3,ite4)
}

//================================================================================================
//  map
//================================================================================================
class map[A,B](f:(A)=>(B), ite:Iterator[A]) extends XIterator[B]{

  def hasNext = ite.hasNext

  def next() = f(ite.next())
}
object map{
  def apply[A,B](f:(A)=>(B), ite:Iterator[A]) = new map(f, ite)
}



